package cn.fresh.xuanyuan.module.trade.api.order;

import cn.fresh.xuanyuan.framework.common.enums.UserTypeEnum;
import cn.fresh.xuanyuan.module.pay.api.order.PayOrderApi;
import cn.fresh.xuanyuan.module.pay.api.order.dto.PayOrderDto;
import cn.fresh.xuanyuan.module.trade.convert.order.TradeOrderConvert;
import cn.fresh.xuanyuan.module.trade.dal.dataobject.order.TradeOrderDO;
import cn.fresh.xuanyuan.module.trade.dal.dataobject.order.TradeOrderItemDO;
import cn.fresh.xuanyuan.module.trade.dal.mysql.order.TradeOrderItemMapper;
import cn.fresh.xuanyuan.module.trade.dal.mysql.order.TradeOrderMapper;
import cn.fresh.xuanyuan.module.trade.dto.UpdateOrderPayStatusDto;
import cn.fresh.xuanyuan.module.trade.enums.order.TradeOrderStatusEnum;
import cn.fresh.xuanyuan.module.trade.framework.order.core.utils.TradeOrderLogUtils;
import cn.fresh.xuanyuan.module.trade.service.order.TradeOrderQueryService;
import cn.fresh.xuanyuan.module.trade.service.order.TradeOrderUpdateService;
import cn.fresh.xuanyuan.framework.common.pojo.CommonResult;
import cn.fresh.xuanyuan.module.trade.api.order.dto.TradeOrderRespDTO;
import cn.fresh.xuanyuan.module.trade.service.order.handler.TradeOrderHandler;
import cn.fresh.xuanyuan.module.trade.service.strategy.SyncOrderStatusStrategy;
import cn.hutool.core.collection.CollectionUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static cn.fresh.xuanyuan.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.fresh.xuanyuan.framework.common.pojo.CommonResult.success;
import static cn.fresh.xuanyuan.module.trade.enums.ErrorCodeConstants.ORDER_UPDATE_PAID_STATUS_NOT_UNPAID;

/**
 * 订单 API 接口实现类
 *
 * @author HUIHUI
 */
@RestController // 提供 RESTful API 接口，给 Feign 调用
@Validated
@Slf4j
public class TradeOrderApiImpl implements TradeOrderApi {

    @Resource
    private TradeOrderUpdateService tradeOrderUpdateService;
    @Resource
    private TradeOrderQueryService tradeOrderQueryService;

    @Resource
    private List<TradeOrderHandler> tradeOrderHandlers;

    @Resource
    private TradeOrderMapper tradeOrderMapper;

    @Resource
    private TradeOrderItemMapper tradeOrderItemMapper;

    @Resource
    private Map<String, SyncOrderStatusStrategy> syncOrderStatusStrategyMap;

    @Resource
    private PayOrderApi payOrderApi;

    private static final ThreadPoolExecutor POOL = new ThreadPoolExecutor(1, 10, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10));


    @Override
    public CommonResult<List<TradeOrderRespDTO>> getOrderList(Collection<Long> ids) {
        return success(TradeOrderConvert.INSTANCE.convertList04(tradeOrderQueryService.getOrderList(ids)));
    }

    @Override
    public CommonResult<TradeOrderRespDTO> getOrder(Long id) {
        return success(TradeOrderConvert.INSTANCE.convert(tradeOrderQueryService.getOrder(id)));
    }

    @Override
    public CommonResult<Boolean> cancelPaidOrder(Long userId, Long orderId) {
        tradeOrderUpdateService.cancelPaidOrder(userId, orderId);
        return success(true);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<Boolean> updateOrderPaid(UpdateOrderPayStatusDto notifyReqDTO) {
        log.info("updateOrderPaid id: {}", notifyReqDTO.getOrderId());
        TradeOrderDO order = tradeOrderMapper.selectById(notifyReqDTO.getOrderId());
        if(order != null) {
            // 2. 更新 TradeOrderDO 状态为已支付，等待发货
            Integer payAmount = order.getPayPrice();
            if(notifyReqDTO.getPayAmount() != null && notifyReqDTO.getPayAmount() > 0) {
                payAmount = notifyReqDTO.getPayAmount();
            }
            int updateCount = tradeOrderMapper.updateByIdAndStatus(notifyReqDTO.getOrderId(), notifyReqDTO.getStatus(),
                    new TradeOrderDO().setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus()).setPayStatus(true)
                            .setPayPrice(payAmount)
                            .setPayTime(LocalDateTime.now()).setPayChannelCode(notifyReqDTO.getChannelCode()));
            if (updateCount == 0) {
                throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID);
            }

            // 3. 执行 TradeOrderHandler 的后置处理
            List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(notifyReqDTO.getOrderId());
            if(Objects.equals(payAmount, order.getPayPrice())) {
                tradeOrderItemMapper.updateItemPaidByOrderId(notifyReqDTO.getOrderId(), TradeOrderStatusEnum.UNDELIVERED.getStatus());
            }
            else {
                
            }
            tradeOrderHandlers.forEach(handler -> handler.afterPayOrder(order, orderItems));

            // 4. 记录订单日志
            TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.UNDELIVERED.getStatus());
            TradeOrderLogUtils.setUserInfo(order.getUserId(), UserTypeEnum.MEMBER.getValue());

            //同步微信订单状态
            List<Long> itemIds = orderItems.stream().map(TradeOrderItemDO::getId).collect(Collectors.toList());
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
                @Override
                public void afterCommit() {
                    pushHandle(order.getId(), itemIds);
                }
            });
            return success(true);
        }

        return success(false);
    }

    @Override
    public CommonResult<Boolean> syncOrderStatusToThirdPart(Map<String, Long> map) {
        return null;
    }

    private void pushHandle(Long orderId, List<Long> itemIds) {
        try {
            TradeOrderDO order = tradeOrderMapper.selectById(orderId);
            List<TradeOrderItemDO> itemList = tradeOrderItemMapper.selectListByIds(itemIds);
            if(order != null && CollectionUtil.isNotEmpty(itemList)) {
                POOL.execute(() -> {
                    pushToThirdPart(order, itemList);
                });
            }
        }
        catch (Exception e) {
            log.error("同步订单状态异常：", e);
        }

    }

    private void pushToThirdPart(TradeOrderDO order, List<TradeOrderItemDO> itemList) {
        PayOrderDto payOrderDto = payOrderApi.getPayOrder(String.valueOf(order.getId())).getCheckedData();
        if(payOrderDto != null) {
//            if("wx_lite".equalsIgnoreCase(payOrderDto.getChannelCode())) {
//                syncOrderStatusStrategyMap.get("wxSyncOrderStatusStrategy").push(order, itemList, payOrderDto);
//            }
            if("douyin_mini".equalsIgnoreCase(payOrderDto.getChannelCode())) {
               syncOrderStatusStrategyMap.get("douYinSyncOrderStatusStrategy").push(order, itemList, payOrderDto);
           }
        }
    }

}
